home *** CD-ROM | disk | FTP | other *** search
/ Aminet 49 / Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso / Aminet / util / libs / ttrender.lha / ttrender-2.0 / Developer / source / sfnt / ttload.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-06  |  69.5 KB  |  1,970 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ttload.c                                                               */
  4. /*                                                                         */
  5. /*    Load the basic TrueType tables, i.e., tables that can be either in   */
  6. /*    TTF or OTF fonts (body).                                             */
  7. /*                                                                         */
  8. /*  Copyright 1996-2001 by                                                 */
  9. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  10. /*                                                                         */
  11. /*  This file is part of the FreeType project, and may only be used,       */
  12. /*  modified, and distributed under the terms of the FreeType project      */
  13. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  14. /*  this file you indicate that you have read the license and              */
  15. /*  understand and accept it fully.                                        */
  16. /*                                                                         */
  17. /***************************************************************************/
  18.  
  19.  
  20. #include <ft2build.h>
  21. #include FT_INTERNAL_DEBUG_H
  22. #include FT_INTERNAL_STREAM_H
  23. #include FT_TRUETYPE_TAGS_H
  24. #include "ttload.h"
  25. #include "ttcmap.h"
  26.  
  27. #include "sferrors.h"
  28.  
  29. #include <stdlib.h>  /* for qsort */
  30. #include <stdio.h>   /* for printf */
  31.  
  32.   /*************************************************************************/
  33.   /*                                                                       */
  34.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  35.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  36.   /* messages during execution.                                            */
  37.   /*                                                                       */
  38. #undef  FT_COMPONENT
  39. #define FT_COMPONENT  trace_ttload
  40.  
  41.  
  42.   /*************************************************************************/
  43.   /*                                                                       */
  44.   /* <Function>                                                            */
  45.   /*    TT_LookUp_Table                                                    */
  46.   /*                                                                       */
  47.   /* <Description>                                                         */
  48.   /*    Looks for a TrueType table by name.                                */
  49.   /*                                                                       */
  50.   /* <Input>                                                               */
  51.   /*    face :: A face object handle.                                      */
  52.   /*    tag  :: The searched tag.                                          */
  53.   /*                                                                       */
  54.   /* <Return>                                                              */
  55.   /*    A pointer to the table directory entry.  0 if not found.           */
  56.   /*                                                                       */
  57.   FT_LOCAL_DEF TT_Table*
  58.   TT_LookUp_Table( TT_Face   face,
  59.                    FT_ULong  tag  )
  60.   {
  61.     TT_Table*  entry;
  62.     TT_Table*  limit;
  63.  
  64.  
  65.     FT_TRACE3(( "TT_LookUp_Table: %08p, `%c%c%c%c' -- ",
  66.                 face,
  67.                 (FT_Char)( tag >> 24 ),
  68.                 (FT_Char)( tag >> 16 ),
  69.                 (FT_Char)( tag >> 8  ),
  70.                 (FT_Char)( tag       ) ));
  71.  
  72.     entry = face->dir_tables;
  73.     limit = entry + face->num_tables;
  74.  
  75.     for ( ; entry < limit; entry++ )
  76.     {
  77.       if ( entry->Tag == tag )
  78.       {
  79.         FT_TRACE3(( "found table.\n" ));
  80.         return entry;
  81.       }
  82.     }
  83.  
  84.     FT_TRACE3(( "could not find table!\n" ));
  85.     return 0;
  86.   }
  87.  
  88.  
  89.   /*************************************************************************/
  90.   /*                                                                       */
  91.   /* <Function>                                                            */
  92.   /*    TT_Goto_Table                                                      */
  93.   /*                                                                       */
  94.   /* <Description>                                                         */
  95.   /*    Looks for a TrueType table by name, then seek a stream to it.      */
  96.   /*                                                                       */
  97.   /* <Input>                                                               */
  98.   /*    face   :: A face object handle.                                    */
  99.   /*    tag    :: The searched tag.                                        */
  100.   /*    stream :: The stream to seek when the table is found.              */
  101.   /*                                                                       */
  102.   /* <Output>                                                              */
  103.   /*    length :: The length of the table if found, undefined otherwise.   */
  104.   /*                                                                       */
  105.   /* <Return>                                                              */
  106.   /*    FreeType error code.  0 means success.                             */
  107.   /*                                                                       */
  108.   FT_LOCAL_DEF FT_Error
  109.   TT_Goto_Table( TT_Face    face,
  110.                  FT_ULong   tag,
  111.                  FT_Stream  stream,
  112.                  FT_ULong*  length )
  113.   {
  114.     TT_Table*  table;
  115.     FT_Error   error;
  116.  
  117.  
  118.     table = TT_LookUp_Table( face, tag );
  119.     if ( table )
  120.     {
  121.       if ( length )
  122.         *length = table->Length;
  123.  
  124.       if ( FILE_Seek( table->Offset ) )
  125.        goto Exit;
  126.     }
  127.     else
  128.       error = SFNT_Err_Table_Missing;
  129.  
  130.   Exit:
  131.     return error;
  132.   }
  133.  
  134.  
  135.   /*************************************************************************/
  136.   /*                                                                       */
  137.   /* <Function>                                                            */
  138.   /*    TT_Load_SFNT_Header                                                */
  139.   /*                                                                       */
  140.   /* <Description>                                                         */
  141.   /*    Loads the header of a SFNT font file.  Supports collections.       */
  142.   /*                                                                       */
  143.   /* <Input>                                                               */
  144.   /*    face       :: A handle to the target face object.                  */
  145.   /*    stream     :: The input stream.                                    */
  146.   /*    face_index :: If the font is a collection, the number of the font  */
  147.   /*                  in the collection, ignored otherwise.                */
  148.   /*                                                                       */
  149.   /* <Output>                                                              */
  150.   /*    sfnt       :: The SFNT header.                                     */
  151.   /*                                                                       */
  152.   /* <Return>                                                              */
  153.   /*    FreeType error code.  0 means success.                             */
  154.   /*                                                                       */
  155.   /* <Note>                                                                */
  156.   /*    The stream cursor must be at the font file's origin.               */
  157.   /*                                                                       */
  158.   /*    This function recognizes fonts embedded in a `TrueType collection' */
  159.   /*                                                                       */
  160.   /*    The header will be checked whether it is valid by looking at the   */
  161.   /*    values of `search_range', `entry_selector', and `range_shift'.     */
  162.   /*                                                                       */
  163.   FT_LOCAL_DEF FT_Error
  164.   TT_Load_SFNT_Header( TT_Face       face,
  165.                        FT_Stream     stream,
  166.                        FT_Long       face_index,
  167.                        SFNT_Header*  sfnt )
  168.   {
  169.     FT_Error   error;
  170.     FT_ULong   format_tag;
  171.     FT_Memory  memory = stream->memory;
  172.  
  173.     const FT_Frame_Field  sfnt_header_fields[] =
  174.     {
  175. #undef  FT_STRUCTURE
  176. #define FT_STRUCTURE  SFNT_Header
  177.  
  178.       FT_FRAME_START( 8 ),
  179.         FT_FRAME_USHORT( num_tables ),
  180.         FT_FRAME_USHORT( search_range ),
  181.         FT_FRAME_USHORT( entry_selector ),
  182.         FT_FRAME_USHORT( range_shift ),
  183.       FT_FRAME_END
  184.     };
  185.  
  186.     const FT_Frame_Field  ttc_header_fields[] =
  187.     {
  188. #undef  FT_STRUCTURE
  189. #define FT_STRUCTURE  TTC_Header
  190.  
  191.       FT_FRAME_START( 8 ),
  192.         FT_FRAME_LONG( version ),
  193.         FT_FRAME_LONG( count   ),
  194.       FT_FRAME_END };
  195.  
  196.  
  197.     FT_TRACE2(( "TT_Load_SFNT_Header: %08p, %ld\n",
  198.                 face, face_index ));
  199.  
  200.     face->ttc_header.tag      = 0;
  201.     face->ttc_header.version  = 0;
  202.     face->ttc_header.count    = 0;
  203.  
  204.     face->num_tables = 0;
  205.  
  206.     /* first of all, read the first 4 bytes.  If it is `ttcf', then the */
  207.     /* file is a TrueType collection, otherwise it can be any other     */
  208.     /* kind of font.                                                    */
  209.     if ( READ_ULong( format_tag ) )
  210.       goto Exit;
  211.  
  212.     if ( format_tag == TTAG_ttcf )
  213.     {
  214.       FT_Int  n;
  215.  
  216.  
  217.       FT_TRACE3(( "TT_Load_SFNT_Header: file is a collection\n" ));
  218.  
  219.       /* it's a TrueType collection, i.e. a file containing several */
  220.       /* font files.  Read the font directory now                   */
  221.       if ( READ_Fields( ttc_header_fields, &face->ttc_header ) )
  222.         goto Exit;
  223.  
  224.       /* now read the offsets of each font in the file */
  225.       if ( ALLOC_ARRAY( face->ttc_header.offsets,
  226.                         face->ttc_header.count,
  227.                         FT_ULong )                     ||
  228.            ACCESS_Frame( face->ttc_header.count * 4L ) )
  229.         goto Exit;
  230.  
  231.       for ( n = 0; n < face->ttc_header.count; n++ )
  232.         face->ttc_header.offsets[n] = GET_ULong();
  233.  
  234.       FORGET_Frame();
  235.  
  236.       /* check face index */
  237.       if ( face_index >= face->ttc_header.count )
  238.       {
  239.         error = SFNT_Err_Bad_Argument;
  240.         goto Exit;
  241.       }
  242.  
  243.       /* seek to the appropriate TrueType file, then read tag */
  244.       if ( FILE_Seek( face->ttc_header.offsets[face_index] ) ||
  245.            READ_Long( format_tag )                           )
  246.         goto Exit;
  247.     }
  248.  
  249.     /* the format tag was read, now check the rest of the header */
  250.     sfnt->format_tag = format_tag;
  251.     if ( READ_Fields( sfnt_header_fields, sfnt ) )
  252.       goto Exit;
  253.  
  254.     /* now, check the values of `num_tables', `seach_range', etc. */
  255.     {
  256.       FT_UInt   num_tables     = sfnt->num_tables;
  257.       FT_ULong  entry_selector = 1L << sfnt->entry_selector;
  258.  
  259.  
  260.       /* IMPORTANT: Many fonts have an incorrect `search_range' value, so */
  261.       /*            we only check the `entry_selector' correctness here.  */
  262.       /*                                                                  */
  263.       if ( num_tables == 0                  ||
  264.            entry_selector > num_tables      ||
  265.            entry_selector * 2 <= num_tables )
  266.       {
  267.         FT_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" ));
  268.         error = SFNT_Err_Unknown_File_Format;
  269.       }
  270.     }
  271.  
  272.   Exit:
  273.     return error;
  274.   }
  275.  
  276.  
  277.   /*************************************************************************/
  278.   /*                                                                       */
  279.   /* <Function>                                                            */
  280.   /*    TT_Load_Directory                                                  */
  281.   /*                                                                       */
  282.   /* <Description>                                                         */
  283.   /*    Loads the table directory into a face object.                      */
  284.   /*                                                                       */
  285.   /* <InOut>                                                               */
  286.   /*    face   :: A handle to the target face object.                      */
  287.   /*                                                                       */
  288.   /* <Input>                                                               */
  289.   /*    stream :: The input stream.                                        */
  290.   /*    sfnt   :: The SFNT directory header.                               */
  291.   /*                                                                       */
  292.   /* <Return>                                                              */
  293.   /*    FreeType error code.  0 means success.                             */
  294.   /*                                                                       */
  295.   /* <Note>                                                                */
  296.   /*    The stream cursor must be at the font file's origin.               */
  297.   /*                                                                       */
  298.   FT_LOCAL_DEF FT_Error
  299.   TT_Load_Directory( TT_Face       face,
  300.                      FT_Stream     stream,
  301.                      SFNT_Header*  sfnt )
  302.   {
  303.     FT_Error   error;
  304.     FT_Memory  memory = stream->memory;
  305.  
  306.     TT_Table *entry, *limit;
  307.  
  308.  
  309.     FT_TRACE2(( "TT_Load_Directory: %08p\n", face ));
  310.  
  311.     FT_TRACE2(( "-- Tables count:   %12u\n",  sfnt->num_tables ));
  312.     FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag ));
  313.  
  314.     face->num_tables = sfnt->num_tables;
  315.  
  316.     if ( ALLOC_ARRAY( face->dir_tables,
  317.                       face->num_tables,
  318.                       TT_Table ) )
  319.       goto Exit;
  320.  
  321.     if ( ACCESS_Frame( face->num_tables * 16L ) )
  322.       goto Exit;
  323.  
  324.     entry = face->dir_tables;
  325.     limit = entry + face->num_tables;
  326.  
  327.     for ( ; entry < limit; entry++ )
  328.     {                    /* loop through the tables and get all entries */
  329.       entry->Tag      = GET_Tag4();
  330.       entry->CheckSum = GET_ULong();
  331.       entry->Offset   = GET_Long();
  332.       entry->Length   = GET_Long();
  333.  
  334.       FT_TRACE2(( "  %c%c%c%c  -  %08lx  -  %08lx\n",
  335.                   (FT_Char)( entry->Tag >> 24 ),
  336.                   (FT_Char)( entry->Tag >> 16 ),
  337.                   (FT_Char)( entry->Tag >> 8  ),
  338.                   (FT_Char)( entry->Tag       ),
  339.                   entry->Offset,
  340.                   entry->Length ));
  341.     }
  342.  
  343.     FORGET_Frame();
  344.  
  345.     FT_TRACE2(( "Directory loaded\n\n" ));
  346.  
  347.   Exit:
  348.     return error;
  349.   }
  350.  
  351.  
  352.   /*************************************************************************/
  353.   /*                                                                       */
  354.   /* <Function>                                                            */
  355.   /*    TT_Load_Any                                                        */
  356.   /*                                                                       */
  357.   /* <Description>                                                         */
  358.   /*    Loads any font table into client memory.                           */
  359.   /*                                                                       */
  360.   /* <Input>                                                               */
  361.   /*    face   :: The face object to look for.                             */
  362.   /*                                                                       */
  363.   /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
  364.   /*              to access the whole font file, else set this parameter   */
  365.   /*              to a valid TrueType table tag that you can forge with    */
  366.   /*              the MAKE_TT_TAG macro.                                   */
  367.   /*                                                                       */
  368.   /*    offset :: The starting offset in the table (or the file if         */
  369.   /*              tag == 0).                                               */
  370.   /*                                                                       */
  371.   /*    length :: The address of the decision variable:                    */
  372.   /*                                                                       */
  373.   /*                If length == NULL:                                     */
  374.   /*                  Loads the whole table.  Returns an error if          */
  375.   /*                  `offset' == 0!                                       */
  376.   /*                                                                       */
  377.   /*                If *length == 0:                                       */
  378.   /*                  Exits immediately; returning the length of the given */
  379.   /*                  table or of the font file, depending on the value of */
  380.   /*                  `tag'.                                               */
  381.   /*                                                                       */
  382.   /*                If *length != 0:                                       */
  383.   /*                  Loads the next `length' bytes of table or font,      */
  384.   /*                  starting at offset `offset' (in table or font too).  */
  385.   /*                                                                       */
  386.   /* <Output>                                                              */
  387.   /*    buffer :: The address of target buffer.                            */
  388.   /*                                                                       */
  389.   /* <Return>                                                              */
  390.   /*    FreeType error code.  0 means success.                             */
  391.   /*                                                                       */
  392.   FT_LOCAL_DEF FT_Error
  393.   TT_Load_Any( TT_Face    face,
  394.                FT_ULong   tag,
  395.                FT_Long    offset,
  396.                FT_Byte*   buffer,
  397.                FT_ULong*  length )
  398.   {
  399.     FT_Error   error;
  400.     FT_Stream  stream;
  401.     TT_Table*  table;
  402.     FT_ULong   size;
  403.  
  404.  
  405.     if ( tag != 0 )
  406.     {
  407.       /* look for tag in font directory */
  408.       table = TT_LookUp_Table( face, tag );
  409.       if ( !table )
  410.       {
  411.         error = SFNT_Err_Table_Missing;
  412.         goto Exit;
  413.       }
  414.  
  415.       offset += table->Offset;
  416.       size    = table->Length;
  417.     }
  418.     else
  419.       /* tag == 0 -- the user wants to access the font file directly */
  420.       size = face->root.stream->size;
  421.  
  422.     if ( length && *length == 0 )
  423.     {
  424.       *length = size;
  425.  
  426.       return SFNT_Err_Ok;
  427.     }
  428.  
  429.     if ( length )
  430.       size = *length;
  431.  
  432.     stream = face->root.stream;
  433.     /* the `if' is syntactic sugar for picky compilers */
  434.     if ( FILE_Read_At( offset, buffer, size ) )
  435.       goto Exit;
  436.  
  437.   Exit:
  438.     return error;
  439.   }
  440.  
  441.  
  442.   /*************************************************************************/
  443.   /*                                                                       */
  444.   /* <Function>                                                            */
  445.   /*    TT_Load_Generic_Header                                             */
  446.   /*                                                                       */
  447.   /* <Description>                                                         */
  448.   /*    Loads the TrueType table `head' or `bhed'.                         */
  449.   /*                                                                       */
  450.   /* <Input>                                                               */
  451.   /*    face   :: A handle to the target face object.                      */
  452.   /*    stream :: The input stream.                                        */
  453.   /*                                                                       */
  454.   /* <Return>                                                              */
  455.   /*    FreeType error code.  0 means success.                             */
  456.   /*                                                                       */
  457.   static FT_Error
  458.   TT_Load_Generic_Header( TT_Face    face,
  459.                           FT_Stream  stream,
  460.                           FT_ULong   tag )
  461.   {
  462.     FT_Error    error;
  463.     TT_Header*  header;
  464.  
  465.     static const FT_Frame_Field  header_fields[] =
  466.     {
  467. #undef  FT_STRUCTURE
  468. #define FT_STRUCTURE  TT_Header
  469.  
  470.       FT_FRAME_START( 54 ),
  471.         FT_FRAME_ULONG ( Table_Version ),
  472.         FT_FRAME_ULONG ( Font_Revision ),
  473.         FT_FRAME_LONG  ( CheckSum_Adjust ),
  474.         FT_FRAME_LONG  ( Magic_Number ),
  475.         FT_FRAME_USHORT( Flags ),
  476.         FT_FRAME_USHORT( Units_Per_EM ),
  477.         FT_FRAME_LONG  ( Created[0] ),
  478.         FT_FRAME_LONG  ( Created[1] ),
  479.         FT_FRAME_LONG  ( Modified[0] ),
  480.         FT_FRAME_LONG  ( Modified[1] ),
  481.         FT_FRAME_SHORT ( xMin ),
  482.         FT_FRAME_SHORT ( yMin ),
  483.         FT_FRAME_SHORT ( xMax ),
  484.         FT_FRAME_SHORT ( yMax ),
  485.         FT_FRAME_USHORT( Mac_Style ),
  486.         FT_FRAME_USHORT( Lowest_Rec_PPEM ),
  487.         FT_FRAME_SHORT ( Font_Direction ),
  488.         FT_FRAME_SHORT ( Index_To_Loc_Format ),
  489.         FT_FRAME_SHORT ( Glyph_Data_Format ),
  490.       FT_FRAME_END
  491.     };
  492.  
  493.  
  494.     FT_TRACE2(( "TT_Load_Generic_Header: "
  495.                 "%08p, looking up font table `%c%c%c%c'.\n",
  496.                 face,
  497.                 (FT_Char)( tag >> 24 ),
  498.                 (FT_Char)( tag >> 16 ),
  499.                 (FT_Char)( tag >> 8  ),
  500.                 (FT_Char)( tag       ) ));
  501.  
  502.     error = face->goto_table( face, tag, stream, 0 );
  503.     if ( error )
  504.     {
  505.       FT_TRACE2(( "TT_Load_Generic_Header: Font table is missing!\n" ));
  506.       goto Exit;
  507.     }
  508.  
  509.     header = &face->header;
  510.  
  511.     if ( READ_Fields( header_fields, header ) )
  512.       goto Exit;
  513.  
  514.     FT_TRACE2(( "    Units per EM: %8u\n", header->Units_Per_EM ));
  515.     FT_TRACE2(( "    IndexToLoc:   %8d\n", header->Index_To_Loc_Format ));
  516.     FT_TRACE2(( "TT_Load_Generic_Header: Font table loaded.\n" ));
  517.  
  518.   Exit:
  519.     return error;
  520.   }
  521.  
  522.  
  523.   FT_LOCAL_DEF FT_Error
  524.   TT_Load_Header( TT_Face    face,
  525.                   FT_Stream  stream )
  526.   {
  527.     return TT_Load_Generic_Header( face, stream, TTAG_head );
  528.   }
  529.  
  530.  
  531. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  532.  
  533.   FT_LOCAL_DEF FT_Error
  534.   TT_Load_Bitmap_Header( TT_Face    face,
  535.                          FT_Stream  stream )
  536.   {
  537.     return TT_Load_Generic_Header( face, stream, TTAG_bhed );
  538.   }
  539.  
  540. #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
  541.  
  542.  
  543.   /*************************************************************************/
  544.   /*                                                                       */
  545.   /* <Function>                                                            */
  546.   /*    TT_Load_MaxProfile                                                 */
  547.   /*                                                                       */
  548.   /* <Description>                                                         */
  549.   /*    Loads the maximum profile into a face object.                      */
  550.   /*                                                                       */
  551.   /* <Input>                                                               */
  552.   /*    face   :: A handle to the target face object.                      */
  553.   /*    stream :: The input stream.                                        */
  554.   /*                                                                       */
  555.   /* <Return>                                                              */
  556.   /*    FreeType error code.  0 means success.                             */
  557.   /*                                                                       */
  558.   FT_LOCAL_DEF FT_Error
  559.   TT_Load_MaxProfile( TT_Face    face,
  560.                       FT_Stream  stream )
  561.   {
  562.     FT_Error        error;
  563.     TT_MaxProfile*  maxProfile = &face->max_profile;
  564.  
  565.     const FT_Frame_Field  maxp_fields[] =
  566.     {
  567. #undef  FT_STRUCTURE
  568. #define FT_STRUCTURE  TT_MaxProfile
  569.  
  570.       FT_FRAME_START( 6 ),
  571.         FT_FRAME_LONG  ( version ),
  572.         FT_FRAME_USHORT( numGlyphs ),
  573.       FT_FRAME_END
  574.     };
  575.  
  576.     const FT_Frame_Field  maxp_fields_extra[] =
  577.     {
  578.       FT_FRAME_START( 26 ),
  579.         FT_FRAME_USHORT( maxPoints ),
  580.         FT_FRAME_USHORT( maxContours ),
  581.         FT_FRAME_USHORT( maxCompositePoints ),
  582.         FT_FRAME_USHORT( maxCompositeContours ),
  583.         FT_FRAME_USHORT( maxZones ),
  584.         FT_FRAME_USHORT( maxTwilightPoints ),
  585.         FT_FRAME_USHORT( maxStorage ),
  586.         FT_FRAME_USHORT( maxFunctionDefs ),
  587.         FT_FRAME_USHORT( maxInstructionDefs ),
  588.         FT_FRAME_USHORT( maxStackElements ),
  589.         FT_FRAME_USHORT( maxSizeOfInstructions ),
  590.         FT_FRAME_USHORT( maxComponentElements ),
  591.         FT_FRAME_USHORT( maxComponentDepth ),
  592.       FT_FRAME_END
  593.     };
  594.  
  595.  
  596.     FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face ));
  597.  
  598.     error = face->goto_table( face, TTAG_maxp, stream, 0 );
  599.     if ( error )
  600.       goto Exit;
  601.  
  602.     if ( READ_Fields( maxp_fields, maxProfile ) )
  603.       goto Exit;
  604.  
  605.     maxProfile->maxPoints             = 0;
  606.     maxProfile->maxContours           = 0;
  607.     maxProfile->maxCompositePoints    = 0;
  608.     maxProfile->maxCompositeContours  = 0;
  609.     maxProfile->maxZones              = 0;
  610.     maxProfile->maxTwilightPoints     = 0;
  611.     maxProfile->maxStorage            = 0;
  612.     maxProfile->maxFunctionDefs       = 0;
  613.     maxProfile->maxInstructionDefs    = 0;
  614.     maxProfile->maxStackElements      = 0;
  615.     maxProfile->maxSizeOfInstructions = 0;
  616.     maxProfile->maxComponentElements  = 0;
  617.     maxProfile->maxComponentDepth     = 0;
  618.  
  619.     if ( maxProfile->version >= 0x10000L )
  620.     {
  621.       if ( READ_Fields( maxp_fields_extra, maxProfile ) )
  622.         goto Exit;
  623.  
  624.       /* XXX: an adjustment that is necessary to load certain */
  625.       /*      broken fonts like `Keystrokes MT' :-(           */
  626.       /*                                                      */
  627.       /*   We allocate 64 function entries by default when    */
  628.       /*   the maxFunctionDefs field is null.                 */
  629.  
  630.       if ( maxProfile->maxFunctionDefs == 0 )
  631.         maxProfile->maxFunctionDefs = 64;
  632.  
  633.       face->root.num_glyphs = maxProfile->numGlyphs;
  634.  
  635.       face->root.internal->max_points =
  636.         (FT_UShort)MAX( maxProfile->maxCompositePoints,
  637.                         maxProfile->maxPoints );
  638.  
  639.       face->root.internal->max_contours =
  640.         (FT_Short)MAX( maxProfile->maxCompositeContours,
  641.                        maxProfile->maxContours );
  642.  
  643.       face->max_components = (FT_ULong)maxProfile->maxComponentElements +
  644.                              maxProfile->maxComponentDepth;
  645.  
  646.       /* XXX: some fonts have maxComponents set to 0; we will */
  647.       /*      then use 16 of them by default.                 */
  648.       if ( face->max_components == 0 )
  649.         face->max_components = 16;
  650.  
  651.       /* We also increase maxPoints and maxContours in order to support */
  652.       /* some broken fonts.                                             */
  653.       face->root.internal->max_points   += (FT_UShort)8;
  654.       face->root.internal->max_contours += (FT_Short) 4;
  655.     }
  656.  
  657.     FT_TRACE2(( "MAXP loaded.\n" ));
  658.  
  659.   Exit:
  660.     return error;
  661.   }
  662.  
  663.  
  664.   /*************************************************************************/
  665.   /*                                                                       */
  666.   /* <Function>                                                            */
  667.   /*    TT_Load_Metrics                                                    */
  668.   /*                                                                       */
  669.   /* <Description>                                                         */
  670.   /*    Loads the horizontal or vertical metrics table into a face object. */
  671.   /*                                                                       */
  672.   /* <Input>                                                               */
  673.   /*    face     :: A handle to the target face object.                    */
  674.   /*    stream   :: The input stream.                                      */
  675.   /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
  676.   /*                                                                       */
  677.   /* <Return>                                                              */
  678.   /*    FreeType error code.  0 means success.                             */
  679.   /*                                                                       */
  680.   static FT_Error
  681.   TT_Load_Metrics( TT_Face    face,
  682.                    FT_Stream  stream,
  683.                    FT_Bool    vertical )
  684.   {
  685.     FT_Error   error;
  686.     FT_Memory  memory = stream->memory;
  687.  
  688.     FT_ULong   table_len;
  689.     FT_Long    num_shorts, num_longs, num_shorts_checked;
  690.  
  691.     TT_LongMetrics**   longs;
  692.     TT_ShortMetrics**  shorts;
  693.  
  694.  
  695.     FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
  696.                                                        : "Horizontal",
  697.                                               face ));
  698.  
  699.     if ( vertical )
  700.     {
  701.       /* The table is optional, quit silently if it wasn't found       */
  702.       /* XXX: Some fonts have a valid vertical header with a non-null  */
  703.       /*      `number_of_VMetrics' fields, but no corresponding `vmtx' */
  704.       /*      table to get the metrics from (e.g. mingliu).            */
  705.       /*                                                               */
  706.       /*      For safety, we set the field to 0!                       */
  707.       /*                                                               */
  708.       error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
  709.       if ( error )
  710.       {
  711.         /* Set number_Of_VMetrics to 0! */
  712.         FT_TRACE2(( "  no vertical header in file.\n" ));
  713.         face->vertical.number_Of_VMetrics = 0;
  714.         error = SFNT_Err_Ok;
  715.         goto Exit;
  716.       }
  717.  
  718.       num_longs = face->vertical.number_Of_VMetrics;
  719.       longs     = (TT_LongMetrics**)&face->vertical.long_metrics;
  720.       shorts    = (TT_ShortMetrics**)&face->vertical.short_metrics;
  721.     }
  722.     else
  723.     {
  724.       error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
  725.       if ( error )
  726.       {
  727.         FT_ERROR(( " no horizontal metrics in file!\n" ));
  728.         error = SFNT_Err_Hmtx_Table_Missing;
  729.         goto Exit;
  730.       }
  731.  
  732.       num_longs = face->horizontal.number_Of_HMetrics;
  733.       longs     = (TT_LongMetrics**)&face->horizontal.long_metrics;
  734.       shorts    = (TT_ShortMetrics**)&face->horizontal.short_metrics;
  735.     }
  736.  
  737.     /* never trust derived values */
  738.  
  739.     num_shorts         = face->max_profile.numGlyphs - num_longs;
  740.     num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
  741.  
  742.     if ( num_shorts < 0 )
  743.     {
  744.       FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
  745.                  vertical ? "Vertical"
  746.                           : "Horizontal" ));
  747.  
  748.       error = vertical ? SFNT_Err_Invalid_Vert_Metrics
  749.                        : SFNT_Err_Invalid_Horiz_Metrics;
  750.       goto Exit;
  751.     }
  752.  
  753.     if ( ALLOC_ARRAY( *longs,  num_longs,  TT_LongMetrics )  ||
  754.          ALLOC_ARRAY( *shorts, num_shorts, TT_ShortMetrics ) )
  755.       goto Exit;
  756.  
  757.     if ( ACCESS_Frame( table_len ) )
  758.       goto Exit;
  759.  
  760.     {
  761.       TT_LongMetrics*  cur   = *longs;
  762.       TT_LongMetrics*  limit = cur + num_longs;
  763.  
  764.  
  765.       for ( ; cur < limit; cur++ )
  766.       {
  767.         cur->advance = GET_UShort();
  768.         cur->bearing = GET_Short();
  769.       }
  770.     }
  771.  
  772.     /* do we have an inconsistent number of metric values? */
  773.     {
  774.       TT_ShortMetrics*  cur   = *shorts;
  775.       TT_ShortMetrics*  limit = cur + MIN( num_shorts, num_shorts_checked );
  776.  
  777.  
  778.       for ( ; cur < limit; cur++ )
  779.         *cur = GET_Short();
  780.  
  781.       /* we fill up the missing left side bearings with the     */
  782.       /* last valid value.  Since this will occur for buggy CJK */
  783.       /* fonts usually only, nothing serious will happen        */
  784.       if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
  785.       {
  786.         FT_Short  val = (*shorts)[num_shorts_checked - 1];
  787.  
  788.  
  789.         limit = *shorts + num_shorts;
  790.         for ( ; cur < limit; cur++ )
  791.           *cur = val;
  792.       }
  793.     }
  794.  
  795.     FORGET_Frame();
  796.  
  797.     FT_TRACE2(( "loaded\n" ));
  798.  
  799.   Exit:
  800.     return error;
  801.   }
  802.  
  803.  
  804.   /*************************************************************************/
  805.   /*                                                                       */
  806.   /* <Function>                                                            */
  807.   /*    TT_Load_Metrics_Header                                             */
  808.   /*                                                                       */
  809.   /* <Description>                                                         */
  810.   /*    Loads the horizontal or vertical header in a face object.          */
  811.   /*                                                                       */
  812.   /* <Input>                                                               */
  813.   /*    face     :: A handle to the target face object.                    */
  814.   /*    stream   :: The input stream.                                      */
  815.   /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
  816.   /*                                                                       */
  817.   /* <Return>                                                              */
  818.   /*    FreeType error code.  0 means success.                             */
  819.   /*                                                                       */
  820.   FT_LOCAL_DEF FT_Error
  821.   TT_Load_Metrics_Header( TT_Face    face,
  822.                           FT_Stream  stream,
  823.                           FT_Bool    vertical )
  824.   {
  825.     FT_Error        error;
  826.     TT_HoriHeader*  header;
  827.  
  828.     const FT_Frame_Field  metrics_header_fields[] =
  829.     {
  830. #undef  FT_STRUCTURE
  831. #define FT_STRUCTURE  TT_HoriHeader
  832.  
  833.       FT_FRAME_START( 36 ),
  834.         FT_FRAME_ULONG ( Version ),
  835.         FT_FRAME_SHORT ( Ascender ),
  836.         FT_FRAME_SHORT ( Descender ),
  837.         FT_FRAME_SHORT ( Line_Gap ),
  838.         FT_FRAME_USHORT( advance_Width_Max ),
  839.         FT_FRAME_SHORT ( min_Left_Side_Bearing ),
  840.         FT_FRAME_SHORT ( min_Right_Side_Bearing ),
  841.         FT_FRAME_SHORT ( xMax_Extent ),
  842.         FT_FRAME_SHORT ( caret_Slope_Rise ),
  843.         FT_FRAME_SHORT ( caret_Slope_Run ),
  844.         FT_FRAME_SHORT ( caret_Offset ),
  845.         FT_FRAME_SHORT ( Reserved[0] ),
  846.         FT_FRAME_SHORT ( Reserved[1] ),
  847.         FT_FRAME_SHORT ( Reserved[2] ),
  848.         FT_FRAME_SHORT ( Reserved[3] ),
  849.         FT_FRAME_SHORT ( metric_Data_Format ),
  850.         FT_FRAME_USHORT( number_Of_HMetrics ),
  851.       FT_FRAME_END
  852.     };
  853.  
  854.  
  855.     FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
  856.  
  857.     if ( vertical )
  858.     {
  859.       face->vertical_info = 0;
  860.  
  861.       /* The vertical header table is optional, so return quietly if */
  862.       /* we don't find it.                                           */
  863.       error = face->goto_table( face, TTAG_vhea, stream, 0 );
  864.       if ( error )
  865.       {
  866.         error = SFNT_Err_Ok;
  867.         goto Exit;
  868.       }
  869.  
  870.       face->vertical_info = 1;
  871.       header = (TT_HoriHeader*)&face->vertical;
  872.     }
  873.     else
  874.     {
  875.       /* The horizontal header is mandatory; return an error if we */
  876.       /* don't find it.                                            */
  877.       error = face->goto_table( face, TTAG_hhea, stream, 0 );
  878.       if ( error )
  879.       {
  880.         error = SFNT_Err_Horiz_Header_Missing;
  881.         goto Exit;
  882.       }
  883.  
  884.       header = &face->horizontal;
  885.     }
  886.  
  887.     if ( READ_Fields( metrics_header_fields, header ) )
  888.       goto Exit;
  889.  
  890.     header->long_metrics  = NULL;
  891.     header->short_metrics = NULL;
  892.  
  893.     FT_TRACE2(( "loaded\n" ));
  894.  
  895.     /* Now try to load the corresponding metrics */
  896.  
  897.     error = TT_Load_Metrics( face, stream, vertical );
  898.  
  899.   Exit:
  900.     return error;
  901.   }
  902.  
  903.  
  904.   /*************************************************************************/
  905.   /*                                                                       */
  906.   /* <Function>                                                            */
  907.   /*    TT_Load_Names                                                      */
  908.   /*                                                                       */
  909.   /* <Description>                                                         */
  910.   /*    Loads the name records.                                            */
  911.   /*                                                                       */
  912.   /* <Input>                                                               */
  913.   /*    face   :: A handle to the target face object.                      */
  914.   /*    stream :: The input stream.                                        */
  915.   /*                                                                       */
  916.   /* <Return>                                                              */
  917.   /*    FreeType error code.  0 means success.                             */
  918.   /*                                                                       */
  919.   FT_LOCAL_DEF FT_Error
  920.   TT_Load_Names( TT_Face    face,
  921.                  FT_Stream  stream )
  922.   {
  923.     FT_Error   error;
  924.     FT_Memory  memory = stream->memory;
  925.  
  926.     FT_ULong   table_pos, table_len;
  927.     FT_ULong   storageSize, storageOffset;
  928.     FT_Byte*   storage;
  929.  
  930.     TT_NameTable*  table;
  931.     TT_NameRec*    names;
  932.     FT_UInt        num_names;
  933.  
  934.     const FT_Frame_Field  name_table_fields[] =
  935.     {
  936. #undef  FT_STRUCTURE
  937. #define FT_STRUCTURE  TT_NameTable
  938.  
  939.       FT_FRAME_START( 6 ),
  940.         FT_FRAME_USHORT( format ),
  941.         FT_FRAME_USHORT( numNameRecords ),
  942.         FT_FRAME_USHORT( storageOffset ),
  943.       FT_FRAME_END
  944.     };
  945.  
  946.     const FT_Frame_Field  name_record_fields[] =
  947.     {
  948. #undef  FT_STRUCTURE
  949. #define FT_STRUCTURE  TT_NameRec
  950.  
  951.       /* no FT_FRAME_START */
  952.         FT_FRAME_USHORT( platformID ),
  953.         FT_FRAME_USHORT( encodingID ),
  954.         FT_FRAME_USHORT( languageID ),
  955.         FT_FRAME_USHORT( nameID ),
  956.         FT_FRAME_USHORT( stringLength ),
  957.         FT_FRAME_USHORT( stringOffset ),
  958.       FT_FRAME_END
  959.     };
  960.  
  961.  
  962.     FT_TRACE2(( "Names " ));
  963.  
  964.     error = face->goto_table( face, TTAG_name, stream, &table_len );
  965.     if ( error )
  966.     {
  967.       /* The name table is required so indicate failure. */
  968.       FT_TRACE2(( "is missing!\n" ));
  969.       error = SFNT_Err_Name_Table_Missing;
  970.       goto Exit;
  971.     }
  972.  
  973.     table_pos = FILE_Pos();
  974.  
  975.     table = &face->name_table;
  976.  
  977.     if ( READ_Fields( name_table_fields, table ) )
  978.       goto Exit;
  979.  
  980.     num_names     = (FT_UInt) table->numNameRecords;
  981.     storageOffset = table->storageOffset;
  982.     storageSize   = (FT_ULong)( table_len - storageOffset );
  983.     
  984.     /* check the storage offset field */
  985.     if ( storageOffset < 6 + 12*num_names ||
  986.          table_len     < storageOffset    )
  987.     {
  988.       FT_TRACE2(( "table is broken.. Ignoring !!\n" ));
  989.       
  990.       table->numNameRecords = 0;
  991.       table->storageOffset  = 0;
  992.       
  993.       error = SFNT_Err_Name_Table_Missing;
  994.       goto Exit;
  995.     }
  996.     
  997.     /* Allocate the array of name records. */
  998.     if ( ALLOC( table->names,
  999.                 num_names*sizeof(table->names[0]) + storageSize ) ||
  1000.          ACCESS_Frame( num_names*12L ) )
  1001.       goto Exit;
  1002.  
  1003.     names   = table->names;
  1004.     storage = (FT_Byte*)(names + num_names);
  1005.  
  1006.     /* Load the name records and determine how much storage is needed */
  1007.     /* to hold the strings themselves.                                */
  1008.     {
  1009.       TT_NameRec*  cur   = names;
  1010.       TT_NameRec*  limit = cur + num_names;
  1011.  
  1012.       for ( ; cur < limit; cur ++ )
  1013.       {
  1014.         if ( READ_Fields( name_record_fields, cur ) )
  1015.           break;
  1016.  
  1017.         /* check the fields */
  1018.         if ( cur->stringOffset + cur->stringLength <= (FT_Long)storageSize )
  1019.           cur->string = storage + cur->stringOffset;
  1020.         else
  1021.         {
  1022.           /* that's an invalid entry !! */
  1023.           cur->stringOffset = 0;
  1024.           cur->string       = NULL;
  1025.         }
  1026.       }
  1027.     }
  1028.  
  1029.     FORGET_Frame();
  1030.     
  1031.     if ( error )
  1032.       goto Exit;
  1033.  
  1034.     storageOffset -= 6 + 12*num_names;
  1035.     if ( FILE_Skip( storageOffset )        ||
  1036.          FILE_Read( storage, storageSize ) )
  1037.       goto Exit;
  1038.  
  1039.  
  1040.     /* Print Name Record Table in case of debugging */
  1041.     if ( FT_TRACE_TEST(3) )
  1042.     {
  1043.       TT_NameRec*  cur   = table->names;
  1044.       TT_NameRec*  limit = cur + num_names;
  1045.  
  1046.  
  1047.       for ( ; cur < limit; cur++ )
  1048.       {
  1049.         FT_UInt  j;
  1050.  
  1051.  
  1052.         printf( "%2d %2d %4x %2d:",
  1053.                  cur->platformID,
  1054.                  cur->encodingID,
  1055.                  cur->languageID,
  1056.                  cur->nameID );
  1057.  
  1058.         /* printf name id */
  1059.         switch ( cur->nameID )
  1060.         {          
  1061.           case 0:  printf( " copyright" ); break;
  1062.           case 1:  printf( " font_family" ); break;
  1063.           case 2:  printf( " style" ); break;
  1064.           case 3:  printf( " unique_id" ); break;
  1065.           case 4:  printf( " full_name" ); break;
  1066.           case 5:  printf( " version" ); break;
  1067.           case 6:  printf( " postscript" ); break;
  1068.           case 7:  printf( " trademark" ); break;
  1069.           case 8:  printf( " manufacturer" ); break;
  1070.           case 9:  printf( " designer" ); break;
  1071.           case 10: printf( " description" ); break;
  1072.           case 11: printf( " url_vendor" ); break;
  1073.           case 12: printf( " url_designer" ); break;
  1074.           case 13: printf( " license" ); break;
  1075.           case 14: printf( " url_license" ); break;
  1076.           case 15: printf( " reserved (15)" ); break;
  1077.           case 16: printf( " prefered_family" ); break;
  1078.           case 17: printf( " prefered_style" ); break;
  1079.           case 18: printf( " mac_full_name" ); break;
  1080.           case 19: printf( " sample_text" ); break;
  1081.           case 20: printf( " cid_name" ); break;
  1082.           default: printf( " unknown_type(%d)", cur->nameID );
  1083.         }
  1084.  
  1085.         /* printf platform/encoding id */
  1086.         j = 0;
  1087.         switch ( cur->platformID )
  1088.         {
  1089.           case 0:  /* Unicode encodings */
  1090.             {
  1091.               switch ( cur->encodingID )
  1092.               {
  1093.                 case 0: printf( " unicode_1.0" ); break;
  1094.                 case 1: printf( " unicode_1.1" ); break;
  1095.                 case 2: printf( " ISO_10646" ); break;
  1096.                 case 3: printf( " unicode_2.0" ); break;
  1097.                 default:
  1098.                   j = 1;
  1099.               }
  1100.               break;
  1101.             }
  1102.           
  1103.           case 1:  /* Apple encodings */
  1104.             {
  1105.               switch ( cur->encodingID )
  1106.               {
  1107.                 case 0: printf( " mac_Roman" ); break;
  1108.                 case 1: printf( " mac_Japanese" ); break;
  1109.                 case 2: printf( " mac_Chinese_traditional" ); break;
  1110.                 case 3: printf( " mac_Korean" ); break;
  1111.                 case 4: printf( " mac_Arabic" ); break;
  1112.                 case 5: printf( " mac_Hebrew" ); break;
  1113.                 case 6: printf( " mac_Greek" ); break;
  1114.                 case 7: printf( " mac_Russian" ); break;
  1115.                 case 8: printf( " mac_RSymbol" ); break;
  1116.                 case 9: printf( " mac_Devanagari" ); break;
  1117.                 case 10: printf( " mac_Gurmukhi" ); break;
  1118.                 case 11: printf( " mac_Gujarati" ); break;
  1119.                 case 12: printf( " mac_Oriya" ); break;
  1120.                 case 13: printf( " mac_Bengali" ); break;
  1121.                 case 14: printf( " mac_Tamil" ); break;
  1122.                 case 15: printf( " mac_Telugu" ); break;
  1123.                 case 16: printf( " mac_Kannada" ); break;
  1124.                 case 17: printf( " mac_Malayalam" ); break;
  1125.                 case 18: printf( " mac_Sinhalese" ); break;
  1126.                 case 19: printf( " mac_Burmese" ); break;
  1127.                 case 20: printf( " mac_Khmer" ); break;
  1128.                 case 21: printf( " mac_Thai" ); break;
  1129.                 case 22: printf( " mac_Laotian" ); break;
  1130.                 case 23: printf( " mac_Goergian" ); break;
  1131.                 case 24: printf( " mac_Armenian" ); break;
  1132.                 case 25: printf( " mac_Chinese_simplified" ); break;
  1133.                 case 26: printf( " mac_Tibetan" ); break;
  1134.                 case 27: printf( " mac_Mongolian" ); break;
  1135.                 case 28: printf( " mac_Geez" ); break;
  1136.                 case 29: printf( " mac_Slavic" ); break;
  1137.                 case 30: printf( " mac_Vietnamese" ); break;
  1138.                 case 31: printf( " mac_Sindhi" ); break;
  1139.                 case 32: printf( " mac_Uninterpreted" ); break;
  1140.                 default:
  1141.                   j = 1;
  1142.               }
  1143.               break;
  1144.             }
  1145.         
  1146.           case 2:  /* deprecated IDO encoding */
  1147.             {
  1148.               switch ( cur->encodingID )
  1149.               {
  1150.                 case 0: printf( " iso_ASCII" ); break;
  1151.                 case 1: printf( " iso_10646" ); break;
  1152.                 case 2: printf( " iso_8859-1" ); break;
  1153.                 default:
  1154.                   j = 1;
  1155.               }
  1156.               break;
  1157.             }
  1158.           
  1159.           case 3:  /* Windows encodings */
  1160.             {
  1161.               switch ( cur->encodingID )
  1162.               {
  1163.                 case 0:  printf( " win_symbol" ); break;
  1164.                 case 1:  printf( " win_unicode" ); break;
  1165.                 case 2:  printf( " win_shiftJIS" ); break;
  1166.                 case 3:  printf( " win_PRC" ); break;
  1167.                 case 4:  printf( " win_Big5" ); break;
  1168.                 case 5:  printf( " win_Wansung" ); break;
  1169.                 case 6:  printf( " win_Johab" ); break;
  1170.                 case 10: printf( " win_UCS4" ); break;
  1171.                 default:
  1172.                   j = 1;
  1173.               }
  1174.               break;
  1175.             }
  1176.           
  1177.           default:
  1178.             j = 1;
  1179.         }
  1180.  
  1181.         if ( j == 1 )
  1182.           printf( " unknown_encoding" );
  1183.  
  1184.         printf( "\n    " );
  1185.  
  1186.         /* printf language - XXXX for later ....*/
  1187.  
  1188.         /* I know that M$ encoded strings are Unicode,            */
  1189.         /* but this works reasonable well for debugging purposes. */
  1190.         if ( cur->string )
  1191.         {
  1192.           for ( j = 0; j < (FT_UInt)cur->stringLength; j++ )
  1193.           {
  1194.             FT_Byte  c = (FT_Byte)*( cur->string + j );
  1195.  
  1196.  
  1197.             if ( c < 32 || c > 127 )
  1198.               c = '.';
  1199.               
  1200.             printf( "%c", c );
  1201.           }
  1202.         }
  1203.         else
  1204.           printf( "INVALID_ENTRY!!" );
  1205.           
  1206.         printf( "\n" );
  1207.       }
  1208.       printf( "\n" );
  1209.     }
  1210.  
  1211.  
  1212.     FT_TRACE2(( "loaded\n" ));
  1213.  
  1214.     /* everything went well, update face->num_names */
  1215.     face->num_names = (FT_UShort)num_names;
  1216.  
  1217.   Exit:
  1218.     return error;
  1219.   }
  1220.  
  1221.  
  1222.   /*************************************************************************/
  1223.   /*                                                                       */
  1224.   /* <Function>                                                            */
  1225.   /*    TT_Free_Names                                                      */
  1226.   /*                                                                       */
  1227.   /* <Description>                                                         */
  1228.   /*    Frees the name records.                                            */
  1229.   /*                                                                       */
  1230.   /* <Input>                                                               */
  1231.   /*    face :: A handle to the target face object.                        */
  1232.   /*                                                                       */
  1233.   FT_LOCAL_DEF void
  1234.   TT_Free_Names( TT_Face  face )
  1235.   {
  1236.     FT_Memory      memory = face->root.driver->root.memory;
  1237.     TT_NameTable*  names  = &face->name_table;
  1238.  
  1239.  
  1240.     /* free strings table */
  1241.     FREE( names->names );
  1242.  
  1243.     /* free strings storage */
  1244.     FREE( names->storage );
  1245.  
  1246.     names->numNameRecords = 0;
  1247.     names->format         = 0;
  1248.     names->storageOffset  = 0;
  1249.   }
  1250.  
  1251.  
  1252.   /*************************************************************************/
  1253.   /*                                                                       */
  1254.   /* <Function>                                                            */
  1255.   /*    TT_Load_CMap                                                       */
  1256.   /*                                                                       */
  1257.   /* <Description>                                                         */
  1258.   /*    Loads the cmap directory in a face object.  The cmaps itselves are */
  1259.   /*    loaded on demand in the `ttcmap.c' module.                         */
  1260.   /*                                                                       */
  1261.   /* <Input>                                                               */
  1262.   /*    face   :: A handle to the target face object.                      */
  1263.   /*    stream :: A handle to the input stream.                            */
  1264.   /*                                                                       */
  1265.   /* <Return>                                                              */
  1266.   /*    FreeType error code.  0 means success.                             */
  1267.   /*                                                                       */
  1268.   FT_LOCAL_DEF FT_Error
  1269.   TT_Load_CMap( TT_Face    face,
  1270.                 FT_Stream  stream )
  1271.   {
  1272.     FT_Error    error;
  1273.     FT_Memory   memory = stream->memory;
  1274.     FT_Long     table_start;
  1275.     TT_CMapDir  cmap_dir;
  1276.  
  1277.     const FT_Frame_Field  cmap_fields[] =
  1278.     {
  1279. #undef  FT_STRUCTURE
  1280. #define FT_STRUCTURE  TT_CMapDir
  1281.  
  1282.       FT_FRAME_START( 4 ),
  1283.         FT_FRAME_USHORT( tableVersionNumber ),
  1284.         FT_FRAME_USHORT( numCMaps ),
  1285.       FT_FRAME_END
  1286.     };
  1287.  
  1288.     const FT_Frame_Field  cmap_rec_fields[] =
  1289.     {
  1290. #undef  FT_STRUCTURE
  1291. #define FT_STRUCTURE  TT_CMapTable
  1292.  
  1293.       FT_FRAME_START( 4 ),
  1294.         FT_FRAME_USHORT( format ),
  1295.         FT_FRAME_USHORT( length ),
  1296.       FT_FRAME_END
  1297.     };
  1298.  
  1299.  
  1300.     FT_TRACE2(( "CMaps " ));
  1301.  
  1302.     error = face->goto_table( face, TTAG_cmap, stream, 0 );
  1303.     if ( error )
  1304.     {
  1305.       error = SFNT_Err_CMap_Table_Missing;
  1306.       goto Exit;
  1307.     }
  1308.  
  1309.     table_start = FILE_Pos();
  1310.  
  1311.     if ( READ_Fields( cmap_fields, &cmap_dir ) )
  1312.       goto Exit;
  1313.  
  1314.     /* reserve space in face table for cmap tables */
  1315.     if ( ALLOC_ARRAY( face->charmaps,
  1316.                       cmap_dir.numCMaps,
  1317.                       TT_CharMapRec ) )
  1318.       goto Exit;
  1319.  
  1320.     face->num_charmaps = cmap_dir.numCMaps;
  1321.     {
  1322.       TT_CharMap  charmap = face->charmaps;
  1323.       TT_CharMap  limit   = charmap + face->num_charmaps;
  1324.  
  1325.  
  1326.       /* read the header of each charmap first */
  1327.       if ( ACCESS_Frame( face->num_charmaps * 8L ) )
  1328.         goto Exit;
  1329.  
  1330.       for ( ; charmap < limit; charmap++ )
  1331.       {
  1332.         TT_CMapTable*  cmap;
  1333.  
  1334.  
  1335.         charmap->root.face = (FT_Face)face;
  1336.         cmap               = &charmap->cmap;
  1337.  
  1338.         cmap->loaded             = FALSE;
  1339.         cmap->platformID         = GET_UShort();
  1340.         cmap->platformEncodingID = GET_UShort();
  1341.         cmap->offset             = (FT_ULong)GET_Long();
  1342.       }
  1343.  
  1344.       FORGET_Frame();
  1345.  
  1346.       /* now read the rest of each table */
  1347.       for ( charmap = face->charmaps; charmap < limit; charmap++ )
  1348.       {
  1349.         TT_CMapTable* cmap = &charmap->cmap;
  1350.  
  1351.  
  1352.         if ( FILE_Seek( table_start + (FT_Long)cmap->offset ) ||
  1353.              READ_Fields( cmap_rec_fields, cmap )             )
  1354.           goto Exit;
  1355.  
  1356.         cmap->offset = FILE_Pos();
  1357.       }
  1358.     }
  1359.  
  1360.     FT_TRACE2(( "loaded\n" ));
  1361.  
  1362.   Exit:
  1363.     return error;
  1364.   }
  1365.  
  1366.  
  1367.   /*************************************************************************/
  1368.   /*                                                                       */
  1369.   /* <Function>                                                            */
  1370.   /*    TT_Load_OS2                                                        */
  1371.   /*                                                                       */
  1372.   /* <Description>                                                         */
  1373.   /*    Loads the OS2 table.                                               */
  1374.   /*                                                                       */
  1375.   /* <Input>                                                               */
  1376.   /*    face   :: A handle to the target face object.                      */
  1377.   /*    stream :: A handle to the input stream.                            */
  1378.   /*                                                                       */
  1379.   /* <Return>                                                              */
  1380.   /*    FreeType error code.  0 means success.                             */
  1381.   /*                                                                       */
  1382.   FT_LOCAL_DEF FT_Error
  1383.   TT_Load_OS2( TT_Face    face,
  1384.                FT_Stream  stream )
  1385.   {
  1386.     FT_Error  error;
  1387.     TT_OS2*   os2;
  1388.  
  1389.     const FT_Frame_Field  os2_fields[] =
  1390.     {
  1391. #undef  FT_STRUCTURE
  1392. #define FT_STRUCTURE  TT_OS2
  1393.  
  1394.       FT_FRAME_START( 78 ),
  1395.         FT_FRAME_USHORT( version ),
  1396.         FT_FRAME_SHORT ( xAvgCharWidth ),
  1397.         FT_FRAME_USHORT( usWeightClass ),
  1398.         FT_FRAME_USHORT( usWidthClass ),
  1399.         FT_FRAME_SHORT ( fsType ),
  1400.         FT_FRAME_SHORT ( ySubscriptXSize ),
  1401.         FT_FRAME_SHORT ( ySubscriptYSize ),
  1402.         FT_FRAME_SHORT ( ySubscriptXOffset ),
  1403.         FT_FRAME_SHORT ( ySubscriptYOffset ),
  1404.         FT_FRAME_SHORT ( ySuperscriptXSize ),
  1405.         FT_FRAME_SHORT ( ySuperscriptYSize ),
  1406.         FT_FRAME_SHORT ( ySuperscriptXOffset ),
  1407.         FT_FRAME_SHORT ( ySuperscriptYOffset ),
  1408.         FT_FRAME_SHORT ( yStrikeoutSize ),
  1409.         FT_FRAME_SHORT ( yStrikeoutPosition ),
  1410.         FT_FRAME_SHORT ( sFamilyClass ),
  1411.         FT_FRAME_BYTE  ( panose[0] ),
  1412.         FT_FRAME_BYTE  ( panose[1] ),
  1413.         FT_FRAME_BYTE  ( panose[2] ),
  1414.         FT_FRAME_BYTE  ( panose[3] ),
  1415.         FT_FRAME_BYTE  ( panose[4] ),
  1416.         FT_FRAME_BYTE  ( panose[5] ),
  1417.         FT_FRAME_BYTE  ( panose[6] ),
  1418.         FT_FRAME_BYTE  ( panose[7] ),
  1419.         FT_FRAME_BYTE  ( panose[8] ),
  1420.         FT_FRAME_BYTE  ( panose[9] ),
  1421.         FT_FRAME_ULONG ( ulUnicodeRange1 ),
  1422.         FT_FRAME_ULONG ( ulUnicodeRange2 ),
  1423.         FT_FRAME_ULONG ( ulUnicodeRange3 ),
  1424.         FT_FRAME_ULONG ( ulUnicodeRange4 ),
  1425.         FT_FRAME_BYTE  ( achVendID[0] ),
  1426.         FT_FRAME_BYTE  ( achVendID[1] ),
  1427.         FT_FRAME_BYTE  ( achVendID[2] ),
  1428.         FT_FRAME_BYTE  ( achVendID[3] ),
  1429.  
  1430.         FT_FRAME_USHORT( fsSelection ),
  1431.         FT_FRAME_USHORT( usFirstCharIndex ),
  1432.         FT_FRAME_USHORT( usLastCharIndex ),
  1433.         FT_FRAME_SHORT ( sTypoAscender ),
  1434.         FT_FRAME_SHORT ( sTypoDescender ),
  1435.         FT_FRAME_SHORT ( sTypoLineGap ),
  1436.         FT_FRAME_USHORT( usWinAscent ),
  1437.         FT_FRAME_USHORT( usWinDescent ),
  1438.       FT_FRAME_END
  1439.     };
  1440.  
  1441.     const FT_Frame_Field  os2_fields_extra[] =
  1442.     {
  1443.       FT_FRAME_START( 8 ),
  1444.         FT_FRAME_ULONG( ulCodePageRange1 ),
  1445.         FT_FRAME_ULONG( ulCodePageRange2 ),
  1446.       FT_FRAME_END
  1447.     };
  1448.  
  1449.     const FT_Frame_Field  os2_fields_extra2[] =
  1450.     {
  1451.       FT_FRAME_START( 10 ),
  1452.         FT_FRAME_SHORT ( sxHeight ),
  1453.         FT_FRAME_SHORT ( sCapHeight ),
  1454.         FT_FRAME_USHORT( usDefaultChar ),
  1455.         FT_FRAME_USHORT( usBreakChar ),
  1456.         FT_FRAME_USHORT( usMaxContext ),
  1457.       FT_FRAME_END
  1458.     };
  1459.  
  1460.  
  1461.     FT_TRACE2(( "OS/2 Table " ));
  1462.  
  1463.     /* We now support old Mac fonts where the OS/2 table doesn't  */
  1464.     /* exist.  Simply put, we set the `version' field to 0xFFFF   */
  1465.     /* and test this value each time we need to access the table. */
  1466.     error = face->goto_table( face, TTAG_OS2, stream, 0 );
  1467.     if ( error )
  1468.     {
  1469.       FT_TRACE2(( "is missing!\n" ));
  1470.       face->os2.version = 0xFFFF;
  1471.       error = SFNT_Err_Ok;
  1472.       goto Exit;
  1473.     }
  1474.  
  1475.     os2 = &face->os2;
  1476.  
  1477.     if ( READ_Fields( os2_fields, os2 ) )
  1478.       goto Exit;
  1479.  
  1480.     os2->ulCodePageRange1 = 0;
  1481.     os2->ulCodePageRange2 = 0;
  1482.     os2->sxHeight         = 0;
  1483.     os2->sCapHeight       = 0;
  1484.     os2->usDefaultChar    = 0;
  1485.     os2->usBreakChar      = 0;
  1486.     os2->usMaxContext     = 0;
  1487.  
  1488.     if ( os2->version >= 0x0001 )
  1489.     {
  1490.       /* only version 1 tables */
  1491.       if ( READ_Fields( os2_fields_extra, os2 ) )
  1492.         goto Exit;
  1493.  
  1494.       if ( os2->version >= 0x0002 )
  1495.       {
  1496.         /* only version 2 tables */
  1497.         if ( READ_Fields( os2_fields_extra2, os2 ) )
  1498.           goto Exit;
  1499.       }
  1500.     }
  1501.  
  1502.     FT_TRACE2(( "loaded\n" ));
  1503.  
  1504.   Exit:
  1505.     return error;
  1506.   }
  1507.  
  1508.  
  1509.   /*************************************************************************/
  1510.   /*                                                                       */
  1511.   /* <Function>                                                            */
  1512.   /*    TT_Load_Postscript                                                 */
  1513.   /*                                                                       */
  1514.   /* <Description>                                                         */
  1515.   /*    Loads the Postscript table.                                        */
  1516.   /*                                                                       */
  1517.   /* <Input>                                                               */
  1518.   /*    face   :: A handle to the target face object.                      */
  1519.   /*    stream :: A handle to the input stream.                            */
  1520.   /*                                                                       */
  1521.   /* <Return>                                                              */
  1522.   /*    FreeType error code.  0 means success.                             */
  1523.   /*                                                                       */
  1524.   FT_LOCAL_DEF FT_Error
  1525.   TT_Load_PostScript( TT_Face    face,
  1526.                       FT_Stream  stream )
  1527.   {
  1528.     FT_Error        error;
  1529.     TT_Postscript*  post = &face->postscript;
  1530.  
  1531.     static const FT_Frame_Field  post_fields[] =
  1532.     {
  1533. #undef  FT_STRUCTURE
  1534. #define FT_STRUCTURE  TT_Postscript
  1535.  
  1536.       FT_FRAME_START( 32 ),
  1537.         FT_FRAME_ULONG( FormatType ),
  1538.         FT_FRAME_ULONG( italicAngle ),
  1539.         FT_FRAME_SHORT( underlinePosition ),
  1540.         FT_FRAME_SHORT( underlineThickness ),
  1541.         FT_FRAME_ULONG( isFixedPitch ),
  1542.         FT_FRAME_ULONG( minMemType42 ),
  1543.         FT_FRAME_ULONG( maxMemType42 ),
  1544.         FT_FRAME_ULONG( minMemType1 ),
  1545.         FT_FRAME_ULONG( maxMemType1 ),
  1546.       FT_FRAME_END
  1547.     };
  1548.  
  1549.  
  1550.     FT_TRACE2(( "PostScript " ));
  1551.  
  1552.     error = face->goto_table( face, TTAG_post, stream, 0 );
  1553.     if ( error )
  1554.       return SFNT_Err_Post_Table_Missing;
  1555.  
  1556.     if ( READ_Fields( post_fields, post ) )
  1557.       return error;
  1558.  
  1559.     /* we don't load the glyph names, we do that in another */
  1560.     /* module (ttpost).                                     */
  1561.     FT_TRACE2(( "loaded\n" ));
  1562.  
  1563.     return SFNT_Err_Ok;
  1564.   }
  1565.  
  1566.  
  1567.   /*************************************************************************/
  1568.   /*                                                                       */
  1569.   /* <Function>                                                            */
  1570.   /*    TT_Load_PCLT                                                       */
  1571.   /*                                                                       */
  1572.   /* <Description>                                                         */
  1573.   /*    Loads the PCL 5 Table.                                             */
  1574.   /*                                                                       */
  1575.   /* <Input>                                                               */
  1576.   /*    face   :: A handle to the target face object.                      */
  1577.   /*    stream :: A handle to the input stream.                            */
  1578.   /*                                                                       */
  1579.   /* <Return>                                                              */
  1580.   /*    FreeType error code.  0 means success.                             */
  1581.   /*                                                                       */
  1582.   FT_LOCAL_DEF FT_Error
  1583.   TT_Load_PCLT( TT_Face    face,
  1584.                 FT_Stream  stream )
  1585.   {
  1586.     static const FT_Frame_Field  pclt_fields[] =
  1587.     {
  1588. #undef  FT_STRUCTURE
  1589. #define FT_STRUCTURE  TT_PCLT
  1590.  
  1591.       FT_FRAME_START( 54 ),
  1592.         FT_FRAME_ULONG ( Version ),
  1593.         FT_FRAME_ULONG ( FontNumber ),
  1594.         FT_FRAME_USHORT( Pitch ),
  1595.         FT_FRAME_USHORT( xHeight ),
  1596.         FT_FRAME_USHORT( Style ),
  1597.         FT_FRAME_USHORT( TypeFamily ),
  1598.         FT_FRAME_USHORT( CapHeight ),
  1599.         FT_FRAME_BYTES ( TypeFace, 16 ),
  1600.         FT_FRAME_BYTES ( CharacterComplement, 8 ),
  1601.         FT_FRAME_BYTES ( FileName, 6 ),
  1602.         FT_FRAME_CHAR  ( StrokeWeight ),
  1603.         FT_FRAME_CHAR  ( WidthType ),
  1604.         FT_FRAME_BYTE  ( SerifStyle ),
  1605.         FT_FRAME_BYTE  ( Reserved ),
  1606.       FT_FRAME_END
  1607.     };
  1608.  
  1609.     FT_Error  error;
  1610.     TT_PCLT*  pclt = &face->pclt;
  1611.  
  1612.  
  1613.     FT_TRACE2(( "PCLT " ));
  1614.  
  1615.     /* optional table */
  1616.     error = face->goto_table( face, TTAG_PCLT, stream, 0 );
  1617.     if ( error )
  1618.     {
  1619.       FT_TRACE2(( "missing (optional)\n" ));
  1620.       pclt->Version = 0;
  1621.       return SFNT_Err_Ok;
  1622.     }
  1623.  
  1624.     if ( READ_Fields( pclt_fields, pclt ) )
  1625.       goto Exit;
  1626.  
  1627.     FT_TRACE2(( "loaded\n" ));
  1628.  
  1629.   Exit:
  1630.     return error;
  1631.   }
  1632.  
  1633.  
  1634.   /*************************************************************************/
  1635.   /*                                                                       */
  1636.   /* <Function>                                                            */
  1637.   /*    TT_Load_Gasp                                                       */
  1638.   /*                                                                       */
  1639.   /* <Description>                                                         */
  1640.   /*    Loads the `gasp' table into a face object.                         */
  1641.   /*                                                                       */
  1642.   /* <Input>                                                               */
  1643.   /*    face   :: A handle to the target face object.                      */
  1644.   /*    stream :: The input stream.                                        */
  1645.   /*                                                                       */
  1646.   /* <Return>                                                              */
  1647.   /*    FreeType error code.  0 means success.                             */
  1648.   /*                                                                       */
  1649.   FT_LOCAL_DEF FT_Error
  1650.   TT_Load_Gasp( TT_Face    face,
  1651.                 FT_Stream  stream )
  1652.   {
  1653.     FT_Error   error;
  1654.     FT_Memory  memory = stream->memory;
  1655.  
  1656.     FT_UInt        j,num_ranges;
  1657.     TT_GaspRange*  gaspranges;
  1658.  
  1659.  
  1660.     FT_TRACE2(( "TT_Load_Gasp: %08p\n", face ));
  1661.  
  1662.     /* the gasp table is optional */
  1663.     error = face->goto_table( face, TTAG_gasp, stream, 0 );
  1664.     if ( error )
  1665.       return SFNT_Err_Ok;
  1666.  
  1667.     if ( ACCESS_Frame( 4L ) )
  1668.       goto Exit;
  1669.  
  1670.     face->gasp.version   = GET_UShort();
  1671.     face->gasp.numRanges = GET_UShort();
  1672.  
  1673.     FORGET_Frame();
  1674.  
  1675.     num_ranges = face->gasp.numRanges;
  1676.     FT_TRACE3(( "number of ranges = %d\n", num_ranges ));
  1677.  
  1678.     if ( ALLOC_ARRAY( gaspranges, num_ranges, TT_GaspRange ) ||
  1679.          ACCESS_Frame( num_ranges * 4L )                     )
  1680.       goto Exit;
  1681.  
  1682.     face->gasp.gaspRanges = gaspranges;
  1683.  
  1684.     for ( j = 0; j < num_ranges; j++ )
  1685.     {
  1686.       gaspranges[j].maxPPEM  = GET_UShort();
  1687.       gaspranges[j].gaspFlag = GET_UShort();
  1688.  
  1689.       FT_TRACE3(( " [max:%d flag:%d]",
  1690.                     gaspranges[j].maxPPEM,
  1691.                     gaspranges[j].gaspFlag ));
  1692.     }
  1693.     FT_TRACE3(( "\n" ));
  1694.  
  1695.     FORGET_Frame();
  1696.     FT_TRACE2(( "GASP loaded\n" ));
  1697.  
  1698.   Exit:
  1699.     return error;
  1700.   }
  1701.  
  1702.  
  1703.   FT_CALLBACK_DEF( int )
  1704.   tt_kern_pair_compare( const void*  a,
  1705.                         const void*  b );
  1706.  
  1707.  
  1708.   /*************************************************************************/
  1709.   /*                                                                       */
  1710.   /* <Function>                                                            */
  1711.   /*    TT_Load_Kern                                                       */
  1712.   /*                                                                       */
  1713.   /* <Description>                                                         */
  1714.   /*    Loads the first kerning table with format 0 in the font.  Only     */
  1715.   /*    accepts the first horizontal kerning table.  Developers should use */
  1716.   /*    the `ftxkern' extension to access other kerning tables in the font */
  1717.   /*    file, if they really want to.                                      */
  1718.   /*                                                                       */
  1719.   /* <Input>                                                               */
  1720.   /*    face   :: A handle to the target face object.                      */
  1721.   /*    stream :: The input stream.                                        */
  1722.   /*                                                                       */
  1723.   /* <Return>                                                              */
  1724.   /*    FreeType error code.  0 means success.                             */
  1725.   /*                                                                       */
  1726.   FT_LOCAL_DEF FT_Error
  1727.   TT_Load_Kern( TT_Face    face,
  1728.                 FT_Stream  stream )
  1729.   {
  1730.     FT_Error   error;
  1731.     FT_Memory  memory = stream->memory;
  1732.  
  1733.     FT_UInt    n, num_tables;
  1734.  
  1735.  
  1736.     /* the kern table is optional; exit silently if it is missing */
  1737.     error = face->goto_table( face, TTAG_kern, stream, 0 );
  1738.     if ( error )
  1739.       return SFNT_Err_Ok;
  1740.  
  1741.     if ( ACCESS_Frame( 4L ) )
  1742.       goto Exit;
  1743.  
  1744.     (void)GET_UShort();         /* version */
  1745.     num_tables = GET_UShort();
  1746.  
  1747.     FORGET_Frame();
  1748.  
  1749.     for ( n = 0; n < num_tables; n++ )
  1750.     {
  1751.       FT_UInt  coverage;
  1752.       FT_UInt  length;
  1753.  
  1754.  
  1755.       if ( ACCESS_Frame( 6L ) )
  1756.         goto Exit;
  1757.  
  1758.       (void)GET_UShort();           /* version                 */
  1759.       length   = GET_UShort() - 6;  /* substract header length */
  1760.       coverage = GET_UShort();
  1761.  
  1762.       FORGET_Frame();
  1763.  
  1764.       if ( coverage == 0x0001 )
  1765.       {
  1766.         FT_UInt          num_pairs;
  1767.         TT_Kern_0_Pair*  pair;
  1768.         TT_Kern_0_Pair*  limit;
  1769.  
  1770.  
  1771.         /* found a horizontal format 0 kerning table! */
  1772.         if ( ACCESS_Frame( 8L ) )
  1773.           goto Exit;
  1774.  
  1775.         num_pairs = GET_UShort();
  1776.  
  1777.         /* skip the rest */
  1778.  
  1779.         FORGET_Frame();
  1780.  
  1781.         /* allocate array of kerning pairs */
  1782.         if ( ALLOC_ARRAY( face->kern_pairs, num_pairs, TT_Kern_0_Pair ) ||
  1783.              ACCESS_Frame( 6L * num_pairs )                             )
  1784.           goto Exit;
  1785.  
  1786.         pair  = face->kern_pairs;
  1787.         limit = pair + num_pairs;
  1788.         for ( ; pair < limit; pair++ )
  1789.         {
  1790.           pair->left  = GET_UShort();
  1791.           pair->right = GET_UShort();
  1792.           pair->value = GET_UShort();
  1793.         }
  1794.  
  1795.         FORGET_Frame();
  1796.  
  1797.         face->num_kern_pairs   = num_pairs;
  1798.         face->kern_table_index = n;
  1799.  
  1800.         /* ensure that the kerning pair table is sorted (yes, some */
  1801.         /* fonts have unsorted tables!)                            */
  1802.         {
  1803.           FT_UInt          i;
  1804.           TT_Kern_0_Pair*  pair0;
  1805.  
  1806.  
  1807.           pair0 = face->kern_pairs;
  1808.  
  1809.           for ( i = 1; i < num_pairs; i++, pair0++ )
  1810.           {
  1811.             if ( tt_kern_pair_compare( pair0, pair0 + 1 ) != -1 )
  1812.             {
  1813.               qsort( (void*)face->kern_pairs, (int)num_pairs,
  1814.                      sizeof ( TT_Kern_0_Pair ), tt_kern_pair_compare );
  1815.               break;
  1816.             }
  1817.           }
  1818.         }
  1819.  
  1820.         goto Exit;
  1821.       }
  1822.  
  1823.       if ( FILE_Skip( length ) )
  1824.         goto Exit;
  1825.     }
  1826.  
  1827.     /* no kern table found -- doesn't matter */
  1828.     face->kern_table_index = -1;
  1829.     face->num_kern_pairs   = 0;
  1830.     face->kern_pairs       = NULL;
  1831.  
  1832.   Exit:
  1833.     return error;
  1834.   }
  1835.  
  1836.  
  1837. #undef  TT_KERN_INDEX
  1838. #define TT_KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
  1839.  
  1840.   FT_CALLBACK_DEF( int )
  1841.   tt_kern_pair_compare( const void*  a,
  1842.                         const void*  b )
  1843.   {
  1844.     TT_Kern_0_Pair*  pair1 = (TT_Kern_0_Pair*)a;
  1845.     TT_Kern_0_Pair*  pair2 = (TT_Kern_0_Pair*)b;
  1846.  
  1847.     FT_ULong  index1 = TT_KERN_INDEX( pair1->left, pair1->right );
  1848.     FT_ULong  index2 = TT_KERN_INDEX( pair2->left, pair2->right );
  1849.  
  1850.  
  1851.     return ( index1 < index2 ? -1 :
  1852.            ( index1 > index2 ?  1 : 0 ));
  1853.   }
  1854.  
  1855. #undef TT_KERN_INDEX
  1856.  
  1857.  
  1858.   /*************************************************************************/
  1859.   /*                                                                       */
  1860.   /* <Function>                                                            */
  1861.   /*    TT_Load_Hdmx                                                       */
  1862.   /*                                                                       */
  1863.   /* <Description>                                                         */
  1864.   /*    Loads the horizontal device metrics table.                         */
  1865.   /*                                                                       */
  1866.   /* <Input>                                                               */
  1867.   /*    face   :: A handle to the target face object.                      */
  1868.   /*    stream :: A handle to the input stream.                            */
  1869.   /*                                                                       */
  1870.   /* <Return>                                                              */
  1871.   /*    FreeType error code.  0 means success.                             */
  1872.   /*                                                                       */
  1873.   FT_LOCAL_DEF FT_Error
  1874.   TT_Load_Hdmx( TT_Face    face,
  1875.                 FT_Stream  stream )
  1876.   {
  1877.     FT_Error  error;
  1878.     FT_Memory memory = stream->memory;
  1879.  
  1880.     TT_Hdmx*  hdmx = &face->hdmx;
  1881.     FT_Long   num_glyphs;
  1882.     FT_Long   record_size;
  1883.  
  1884.  
  1885.     hdmx->version     = 0;
  1886.     hdmx->num_records = 0;
  1887.     hdmx->records     = 0;
  1888.  
  1889.     /* this table is optional */
  1890.     error = face->goto_table( face, TTAG_hdmx, stream, 0 );
  1891.     if ( error )
  1892.       return SFNT_Err_Ok;
  1893.  
  1894.     if ( ACCESS_Frame( 8L ) )
  1895.       goto Exit;
  1896.  
  1897.     hdmx->version     = GET_UShort();
  1898.     hdmx->num_records = GET_Short();
  1899.     record_size       = GET_Long();
  1900.  
  1901.     FORGET_Frame();
  1902.  
  1903.     /* Only recognize format 0 */
  1904.     if ( hdmx->version != 0 )
  1905.       goto Exit;
  1906.  
  1907.     if ( ALLOC_ARRAY( hdmx->records, hdmx->num_records, TT_HdmxRec ) )
  1908.       goto Exit;
  1909.  
  1910.     num_glyphs   = face->root.num_glyphs;
  1911.     record_size -= num_glyphs + 2;
  1912.  
  1913.     {
  1914.       TT_HdmxRec*  cur   = hdmx->records;
  1915.       TT_HdmxRec*  limit = cur + hdmx->num_records;
  1916.  
  1917.  
  1918.       for ( ; cur < limit; cur++ )
  1919.       {
  1920.         /* read record */
  1921.         if ( READ_Byte( cur->ppem      ) ||
  1922.              READ_Byte( cur->max_width ) )
  1923.           goto Exit;
  1924.  
  1925.         if ( ALLOC( cur->widths, num_glyphs )     ||
  1926.              FILE_Read( cur->widths, num_glyphs ) )
  1927.           goto Exit;
  1928.  
  1929.         /* skip padding bytes */
  1930.         if ( record_size > 0 && FILE_Skip( record_size ) )
  1931.             goto Exit;
  1932.       }
  1933.     }
  1934.  
  1935.   Exit:
  1936.     return error;
  1937.   }
  1938.  
  1939.  
  1940.   /*************************************************************************/
  1941.   /*                                                                       */
  1942.   /* <Function>                                                            */
  1943.   /*    TT_Free_Hdmx                                                       */
  1944.   /*                                                                       */
  1945.   /* <Description>                                                         */
  1946.   /*    Frees the horizontal device metrics table.                         */
  1947.   /*                                                                       */
  1948.   /* <Input>                                                               */
  1949.   /*    face :: A handle to the target face object.                        */
  1950.   /*                                                                       */
  1951.   FT_LOCAL_DEF void
  1952.   TT_Free_Hdmx( TT_Face  face )
  1953.   {
  1954.     if ( face )
  1955.     {
  1956.       FT_Int     n;
  1957.       FT_Memory  memory = face->root.driver->root.memory;
  1958.  
  1959.  
  1960.       for ( n = 0; n < face->hdmx.num_records; n++ )
  1961.         FREE( face->hdmx.records[n].widths );
  1962.  
  1963.       FREE( face->hdmx.records );
  1964.       face->hdmx.num_records = 0;
  1965.     }
  1966.   }
  1967.  
  1968.  
  1969. /* END */
  1970.